Haskell in Depth by Vitaly Bragilevsky

Haskell in Depth by Vitaly Bragilevsky

Author:Vitaly Bragilevsky [Bragilevsky, Vitaly]
Language: eng
Format: epub, pdf
Publisher: Manning Publications Co.
Published: 0101-01-01T00:00:00+00:00


9.2.2 Defining data types with unboxed values

GHC provides several tools to ask for unboxing. Let’s overview them in this section.

The UNPACK pragma and corresponding optimizations

As we discussed in the previous section, storing values like Rectangle 3 5 requires many closures for the value itself and for each of its fields. If our fields are small, it may be helpful to put them directly into the payload of the constructor’s closure. This is done with the UNPACK pragma, which can be used as follows:

data Shape = Rectangle {-# UNPACK #-} !Int {-# UNPACK #-} !Int | Circle {-# UNPACK #-} !Int

Note that it is required to have strictness flags on all the unpacked fields. The UNPACK pragma has an effect only when optimizations are turned on (compilation with the -O family of flags). Note also that this pragma has no effect on polymorphic values.

Depending on what we are doing with the fields after matching over the constructor pattern, it may be necessary to rebox them, so this optimization does not always lead to reduced memory usage. Anyway, GHC tries hard to avoid reboxing.

GHC options on unboxing In addition to the UNPACK pragma, GHC provides the -funbox-strict-fields flag, which has the effect of adding {-# UNPACK #-} to every strict constructor field. Note that using it could lead to performance drawbacks if we copy a data structure extensively because all the unboxed fields have to be copied. Remember that any change in a data structure leads to copying in Haskell. This is not a problem for small, strict fields if their size is no bigger than a pointer—the pointer has to be copied anyway. That’s why GHC enables the -funbox-small-strict-fields flag by default.

Unboxed tuples and unboxed sums

We are not allowed to define primitive unboxed types, but we are able to define unboxed tuples and unboxed sums using the UnboxedTuples and UnboxedSums GHC extensions. The idea behind these extensions is to make possible declaring complex types without the need to create closures for storing their values. Both unboxed tuples and unboxed sums don’t exist at run time, but their components do exist and are stored in memory, depending on their own types.

Example: Unboxing tuples and sums

ch09/unboxed.hs

unboxed

We can reduce memory allocation thanks to unboxing.

Let’s define a function that computes the sum and product of two numbers and returns them as an unboxed tuple, as shown next:

{-# LANGUAGE UnboxedTuples #-} sum_prod :: Num a => a -> a -> (# a, a #) sum_prod a b = (# a + b, a*b #)

To use this function, we pattern match on its result right after calling it as follows:

test_sum_prod = case sum_prod 5 6 of (# s, p #) -> print (s + p)

In this case, we avoid creating closures for tuples in memory. Doing so may be beneficial if we call this function many times and use its results right away.

The function returning an unboxed tuple may be recursive, as shown here:

{-# LANGUAGE UnboxedTuples #-} fib_next :: Int -> (# Integer, Integer #) -> (#



Download



Copyright Disclaimer:
This site does not store any files on its server. We only index and link to content provided by other sites. Please contact the content providers to delete copyright contents if any and email us, we'll remove relevant links or contents immediately.